/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.querydsl.sql;

import com.querydsl.core.types.ConstantImpl;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.Ops;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.core.types.dsl.SimplePath;
import net.apexes.commons.lang.Enume;

import javax.annotation.Nullable;

/**
 * 
 * @author <a href="mailto:hedyn@foxmail.com">HeDYn</a>
 *
 * @param <T>
 */
public class EnumePath<T extends Enume<?>> extends SimplePath<T> {
    
    private static final long serialVersionUID = 1L;
    
    @Nullable
    private transient volatile OrderSpecifier<T> asc, desc;

    public EnumePath(Class<? extends T> type, PathMetadata metadata) {
        super(type, metadata);
    }

    /**
     * Create a {@code this >= right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this >= right}
     */
    public final <A extends Enume<?>> BooleanExpression goe(A right) {
        return goe(ConstantImpl.create(right));
    }

    /**
     * Create a {@code this >= right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this >= right}
     */
    public final <A extends Enume<?>> BooleanExpression goe(Expression<A> right) {
        return Expressions.booleanOperation(Ops.GOE, mixin, right);
    }

    /**
     * Create a {@code this > right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this > right}
     * @see java.lang.Comparable#compareTo(Object)
     */
    public final <A extends Enume<?>> BooleanExpression gt(A right) {
        return gt(ConstantImpl.create(right));
    }

    /**
     * Create a {@code this > right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this > right}
     */
    public final <A extends Enume<?>> BooleanExpression gt(Expression<A> right) {
        return Expressions.booleanOperation(Ops.GT, mixin, right);
    }

    /**
     * Create a {@code this <= right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this <= right}
     */
    public final <A extends Enume<?>> BooleanExpression loe(A right) {
        return loe(ConstantImpl.create(right));
    }

    /**
     * Create a {@code this <= right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this <= right}
     */
    public final <A extends Enume<?>> BooleanExpression loe(Expression<A> right) {
        return Expressions.booleanOperation(Ops.LOE, mixin, right);
    }

    /**
     * Create a {@code this < right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this < right}
     */
    public final <A extends Enume<?>> BooleanExpression lt(A right) {
        return lt(ConstantImpl.create(right));
    }

    /**
     * Create a {@code this < right} expression
     *
     * @param right rhs of the comparison
     * @return {@code this < right}
     */
    public final <A extends Enume<?>> BooleanExpression lt(Expression<A> right) {
        return Expressions.booleanOperation(Ops.LT, this, right);
    }

    /**
     * Create an OrderSpecifier for ascending order of this expression
     *
     * @return ascending order by this
     */
    public final OrderSpecifier<T> asc() {
        if (asc == null) {
            asc = new OrderSpecifier<T>(Order.ASC, mixin);
        }
        return asc;
    }
    
    /**
     * Create an OrderSpecifier for descending order of this expression
     *
     * @return descending order by this
     */
    public final OrderSpecifier<T> desc() {
        if (desc == null) {
            desc = new OrderSpecifier<T>(Order.DESC, mixin);
        }
        return desc;
    }

}
